﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Model;
using HighDiveEngine.Resources;

namespace HighDiveAdmin.GUI
{
    public partial class FormMain : Form, IFormMain
    {        
        private FormPanels _activePanel;

        #region Constructor
        public FormMain()
        {
            InitializeComponent();
            ActivePanel = FormPanels.Welcome;
            savingContest.Visible = false;
            savingContest.BringToFront();

        }

        #endregion

        #region IFormMain Events

        public event DelegateVoidJudgeEventArgs EventSaveJudge;
        public event DelegateVoidNullableInt EventEditRunningDive;
        public event DelegateVoidDiveEventArgs EventSaveEditedDive;
        public event DelegateDiveListDiver EventEditContestLoadDiveList;
        public event DelegateVoidInt EventEditContestAddDiver;
        public event MethodInvoker EventLoadWelcomeScreen;
        public event MethodInvoker EventLoadEditScreen;
        public event MethodInvoker EventLoadEditScreenNewContest;
        public event DelegateVoidNullableInt EventLoadRunningScreen;
        public event MethodInvoker EventSelectContestToRun;
        public event DelegateVoidContest EventLoadContestToEdit;
        public event DelegateVoidDoubleInt EventManualScoreEntry;
        public event DelegateVoidString EventLoadDiver;
        public event DelegateDoubleStringInt EventCalculateDiveDifficulty;
        public event DelegateVoidString EventEditContestLoadJudge;
        public event DelegateContestInformation EventUpdateContestInformation;
        public event DelegateVoidString EventLoadJudge;
        public event DelegateVoidContestEventArgs EventSaveContest;
        //public event DelegateVoidContestEventArgs EventUpdateContestInformation;
        public event DelegateNewJudge EventNewJudge;
        public event DelegateNewJudge EventUpdateJudge;
        public event DelegateVoidInt EventSetNumberOfJudges;
        public event DelegateVoidBool EventStartContest;
        public event MethodInvoker EventEndContest;
        public event MethodInvoker EventStartOfflineContest;
        public event DelegateVoidStringInt EventUpdateActiveJudge;
        public event DelegateVoidPersonEventArgsDiveEventArgsArray EventEditContestSaveDiver;
        public event DelegateVoidString EventEditContestEditDiver;
        public event MethodInvoker EventDiscardContest;
        public event DelegateJudgeInt EventEditContestAddEditJudge;
        public event DelegateVoidContestEventArgs EventSaveAndStartContest;
        public event DelegateDiverEventArgs EventRemoveDiver;
        public event DelegateDiveEventArgs EventRemoveDive;


        #endregion

        #region SetActivePanel
        public FormPanels ActivePanel
        {
            get
            {
                return _activePanel;
            }
            set
            {
                _activePanel = value;

                editContestScreen.Visible = false;
                runningContestScreen.Visible = false;
                welcomeScreen.Visible = false;

                switch (_activePanel)
                {
                    case FormPanels.Editview:
                        editContestScreen.Visible = true;
                        break;
                    case FormPanels.Running:
                        runningContestScreen.Visible = true;
                        break;
                    case FormPanels.Welcome:
                        welcomeScreen.Visible = true;
                        break;
                }
            }
        }

        #endregion       

        #region StaticMethods
        public static void PopulateTreeFromDiveList(TreeView treeView, DiveList diveList, bool expandAll)
        {
            treeView.Nodes.Clear();
            var divers = new List<KeyValuePair<Diver, DiveList>>();
            foreach (var dive in diveList)
            {
                var pair = divers.Find(x => x.Key.IdNumber == dive.Diver.IdNumber);
                if (pair.Key == null)
                    divers.Add(new KeyValuePair<Diver, DiveList>(dive.Diver, new DiveList { dive }));
                else
                    pair.Value.Add(dive);
            }

            foreach (var diver in divers)
            {
                treeView.Nodes.Add(new DiverTreeNode(diver.Key, diver.Value));
            }
            if (expandAll)
                treeView.ExpandAll();
        }
        #endregion        

        #region Welcome Screen

        public void ShowWelcomeScreenStartContestList(ContestList contestList)
        {
            var startContestList = new StartContestList(contestList);

            if (startContestList.ShowDialog() == DialogResult.OK)
            {
                if (EventLoadRunningScreen != null)
                    EventLoadRunningScreen(startContestList.Index);
            }
        }

        public void ShowWelcomeScreenNoContestsLoadedError()
        {
            MessageBox.Show(@"No contests to start.\nPlease create one.", @"No Unstarted Contests", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        public void FillWelcomeScreenUpcomingContests(ContestList upcomingList)
        {
            welcomeScreen.FillUpcomingContests(upcomingList);
        }

        #region Events
        private void welcomeScreen_EventStartContest()
        {
            if (EventSelectContestToRun != null)
                EventSelectContestToRun();
        } 
        private void welcomeScreen_EventLoadUpcoming(Contest contest)
        {
            if (EventLoadContestToEdit != null)
                EventLoadContestToEdit(contest);
            if (EventLoadEditScreen != null)
                EventLoadEditScreen();
        } 
        private void welcomeScreen_EventCreateContest()
        {
            if (EventLoadEditScreenNewContest != null)
            {
                editContestScreen.SetCreateContest(true);
                EventLoadEditScreenNewContest();
            }
        }
        private void welcomeScreen_EventEditContest()
        {
            if (EventLoadEditScreen != null)
            {
                editContestScreen.SetCreateContest(false);
                EventLoadEditScreen();
            }
        }

        #endregion

        #endregion

        #region Running Contest Screen

        public void ShowRunningContestSaveContestProgress()
        {
            runningContestScreen.Enabled = false;
            savingContest.Visible = true;
        }

        public void CloseRunningContestSaveContestProgress()
        {
            runningContestScreen.Enabled = true;
            savingContest.Visible = false;
        }

        public void ShowRunningContestCompletedPanel()
        {
            runningContestScreen.ShowContestCompleted();
        }

        public void FillRunningContestDiveQueue(DiveList diveQueueList)
        {
            runningContestScreen.FillDiveQueue(diveQueueList);
        }

        public void FillRunningContestDiveResults(DiveList diveResults)
        {
            runningContestScreen.FillDiveResults(diveResults);
        }

        public void FillRunningContestActiveDive(Dive dive)
        {
            runningContestScreen.FillActiveDive(dive);
        }

        public void FillRunningContestJudgeScore(DiveScore score)
        {
            runningContestScreen.FillJudgeScore(score);
        }

        public void SetRunningContestNumVisibleJudges(JudgeList judgeList)
        {
            runningContestScreen.FillJudgeBoxes(judgeList);
        }

        public void FillRunningContestDiveHistory(DiveList diveHistory)
        {
            runningContestScreen.FillDiveHistory(diveHistory);
        }

        public void ShowRunningContestConnectionPhase(JudgeList judgeList, string adminIp)
        {
            runningContestScreen.ShowConnectionPhase(judgeList, adminIp);
        }

        public void UpdateRunningContestJudgeConnectionStatus(Judge judge)
        {
            runningContestScreen.UpdateJudgeConnectionStatus(judge);
        }

        public void HideRunningContestConnectionPhase()
        {
            runningContestScreen.HideConnectionPhase();
        }

        #region Events
        private void runningContestScreen_EventStartContest()
        {
            if (EventStartContest != null)
                EventStartContest(false);
        }
        private void runningContestScreen_EventStartOffline()
        {
            if (EventStartContest != null)
                EventStartContest(true);
        }

        private void runningContestScreen_EventManualScoreEntry(double score, int judgeNumber)
        {
            if (EventManualScoreEntry != null)
                EventManualScoreEntry(score, judgeNumber);
        }

        private void runningContestScreen_EventEndContest()
        {
            if (EventEndContest != null)
                EventEndContest();
        }

        private void runningContestScreen_EventCancel()
        {
            if (EventLoadWelcomeScreen != null)
                EventLoadWelcomeScreen();
        }

        #endregion

        #endregion

        #region Edit Contest Screen

        public void FillEditContestNewDiverPanel(Diver diver, DiveList diveList)
        {
            editContestScreen.FillNewDiverPanel(diver, diveList);
        }

        public void FillEditContestNewJudgePanel(Judge judge)
        {
            editContestScreen.FillNewJudgePanel(judge);
        }

        public void UpdatePersonLists(PersonList personList)
        {
            editContestScreen.UpdatePersonLists(personList);
        }

        public void FillEditContestExistingJudgeFromIdNumber(Person person)
        {
            editContestScreen.FillExistingJudgeFromIdNumber(person);
        }

        public void ShowEditContestNewJudgePanel(Judge judge)
        {
            editContestScreen.ShowNewJudgePanel(judge);
        }

        public void ShowEditContestJudgesPanel(JudgeList judgeList)
        {
            editContestScreen.ShowJudgesPanel(judgeList);
        }

        public void ShowEditContestDiverTreeView(DiveList diveList)
        {
            editContestScreen.ShowDiverTreeView(diveList);
        }

        public void FillEditContestScreenWithContest(Contest contest, PersonList personList)
        {
            editContestScreen.FillEditorWithContest(contest, personList);
        }

        public void FillEditContestScreenContestList(ContestList contestHistoryList)
        {
            editContestScreen.FillContestHistory(contestHistoryList);
        }

        public void FillEditContestExistingDiverFromIdNumber(Person person)
        {
            editContestScreen.FillExistingDiverFromIdNumber(person);
        }

        private void editContestScreen_GoBackToWelcome()
        {
            if (EventLoadWelcomeScreen != null)
                EventLoadWelcomeScreen();
        }

        private void editContestScreen_EventSetNumberOfJudges(int number)
        {
            if (EventSetNumberOfJudges != null)
                EventSetNumberOfJudges(number);
        }

        #region Events
        private void editContestScreen_EventUpdateActiveJudge(string str, int i)
        {
            if (EventUpdateActiveJudge != null)
                EventUpdateActiveJudge(str, i);
        }

        private void editContestScreen_EventLoadDiver(string idNumber)
        {
            if (EventLoadDiver != null)
                EventLoadDiver(idNumber);
        }

        private double editContestScreen_EventCalculateDiveDifficulty(string str, int i)
        {
            if (EventCalculateDiveDifficulty != null) 
                return EventCalculateDiveDifficulty(str, i);
            return 0;
        }
        
        private void runningContestScreen_EventSaveEditedDive(DiveEventArgs diveArgs)
        {
            if (EventSaveEditedDive != null)
                EventSaveEditedDive(diveArgs);
        }

        private void runningContestScreen_EventEditDiveInQueue(int? id)
        {
            if (EventEditRunningDive != null)
                EventEditRunningDive(id);
        }

        private void editContestScreen_EventSaveJudge(JudgeEventArgs judgeArgs)
        {
            if (EventSaveJudge != null)
                EventSaveJudge(judgeArgs);
        }

        #endregion

        #endregion

        private void _appExit()
        {
            Close();
        }

        public void UpdateContestList(ContestList contestList)
        {
            editContestScreen.UpdateContestList(contestList);
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == (Keys.Tab | Keys.Control))
            {
                if (runningContestScreen.Visible)
                    runningContestScreen.ProcessCtrlTab();
                if (editContestScreen.Visible)
                    editContestScreen.ProcessCtrlTab();
                //if (welcomeScreen.Visible)
                //    welcomeScreen.ProcessCtrlTab();
            } 
            else if (keyData == (Keys.Tab | Keys.Control | Keys.Shift))
            {
                if (runningContestScreen.Visible)
                    runningContestScreen.ProcessShiftCtrlTab();
                if (editContestScreen.Visible)
                    editContestScreen.ProcessShiftCtrlTab();
                //if (welcomeScreen.Visible)
                //    welcomeScreen.ProcessShiftCtrlTab();
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void editContestScreen_EventEditContestAddDiver(int startNumber)
        {
            if (EventEditContestAddDiver != null)
                EventEditContestAddDiver(startNumber);
        }

        private DiveList editContestScreen_EventEditContestLoadDiveList(Diver diver)
        {
            if (EventEditContestLoadDiveList != null)
                return EventEditContestLoadDiveList(diver);
            return null;
        }

        private void editContestScreen_EventSaveDiver(DiverEventArgs personArgs, DiveEventArgs[] diveArgs)
        {
            if (EventEditContestSaveDiver != null)
                EventEditContestSaveDiver(personArgs, diveArgs);
        }

        private void editContestScreen_EventEditDiver(string idNumber)
        {
            if (EventEditContestEditDiver != null) 
                EventEditContestEditDiver(idNumber);
        }

        private void editContestScreen_EventLoadContestToEdit(Contest contest)
        {
            if (EventLoadContestToEdit != null) 
                EventLoadContestToEdit(contest);
        }

        private void editContestScreen_EventDiscard(bool goBackToWelcomeScreen)
        {
            if (EventDiscardContest != null)
                EventDiscardContest();
            if(goBackToWelcomeScreen && EventLoadWelcomeScreen != null)
                EventLoadWelcomeScreen();
        }

        private void editContestScreen_EventSave(ContestArgs contestArgs)
        {
            if (EventSaveContest != null)
                EventSaveContest(contestArgs);
        }


        private void editContestScreen_EventLoadJudge(string idNumber)
        {
            if (EventEditContestLoadJudge != null) 
                EventEditContestLoadJudge(idNumber);
        }

        private Judge editContestScreen_EventAddEditJudge(int judgeNumber)
        {
            if (EventEditContestAddEditJudge != null) 
                return EventEditContestAddEditJudge(judgeNumber);
            return null;
        }


        public void ShowEditContestNewJudgePanel(Judge judge, int textBoxNumber)
        {
            throw new NotImplementedException();
        }


        public void UpdateJudgeScoreInHistory(Dive dive)
        {
            runningContestScreen.UpdateJudgeScoreInHistory(dive);
        }

        private void editContestScreen_EventSaveAndStart(ContestArgs contestArgs)
        {
            if (EventSaveAndStartContest != null)
                EventSaveAndStartContest(contestArgs);
        }
        private void editContestScreen_EventRemoveDive(DiveEventArgs diveEventArgs)
        {
            if (EventRemoveDive != null)
                EventRemoveDive(diveEventArgs);
        }

        private void editContestScreen_EventRemoveDiver(DiverEventArgs diverEventArgs)
        {
            if (EventRemoveDiver != null)
                EventRemoveDiver(diverEventArgs);
        }

    }
}
